module klang.编译.源映射生成器.源映射_;
import 全局;
import std.conv: ·to = to;
import klang.编译.类型.枚举值.枚举值_: 字符_;
import klang.编译.类型.类型_: 编译选项基类_, 程序主机接口_, 行和列_, RawSourceMap, SourceMapGenerator;
import klang.编译.核心.核心_: 整数_, 词典_, 创建数组, 返回零值, trimEndImpl, 循环每个, 部分, 二分搜索自选键, 比较器比较值;
import klang.编译.路径.路径_: 获取相对路径到目录或URL, 组合路径, 获取目录路径, 获取正规化绝对路径;
import klang.编译.扫描工具.扫描工具_: 计算位置的行和列;
import klang.编译.json.JSON: 创建JSON空对象, JSON值_, JSON类型_;
dstring[] rawSources;
dstring[] sources;
词典_!(long) sourceToSourceIndexMap;
dstring[] sourcesContent;
dstring[] names;
词典_!(long) nameToNameIndexMap;
const(dchar)[] mappingCharCodes;
dstring mappings;
// Last recorded and encoded mappings
long lastGeneratedLine;
long lastGeneratedCharacter;
long lastSourceIndex;
long lastSourceLine;
long lastSourceCharacter;
long lastNameIndex;
bool hasLast;
long pendingGeneratedLine;
long pendingGeneratedCharacter;
long pendingSourceIndex;
long pendingSourceLine;
long pendingSourceCharacter;
long pendingNameIndex;
bool hasPending;
bool hasPendingSource;
bool hasPendingName;
dstring _sourcesDirectoryPath;
程序主机接口_ _host;
dstring _file;
dstring _sourceRoot;
// Sometimes tools can see the following line as a source mapping url comment, so we mangle it a bit (the [M])
正则_!(dchar) sourceMapCommentRegExp;
正则_!(dchar) whitespaceOrMapCommentRegExp;
static this() {
    sourceMapCommentRegExp = ·regex(r"^\/\/[@#] source[M]appingURL=(.+)$"d, "g"c);
    whitespaceOrMapCommentRegExp = ·regex(r"^\s*(\/\/[@#] .*)?$"d, "g"c);
}
class KlangSourceMapGenerator : SourceMapGenerator {
    this() { }
    dstring[] getSources() {
        return .rawSources;
    }
    long addSource(dstring fileName) {
        return .addSource(fileName);
    }
    void setSourceContent(long sourceIndex, dstring content) {
        .setSourceContent(sourceIndex, content);
    }
    long addName(dstring name) {
        return .addName(name);
    }
    void addMapping(long generatedLine, long generatedCharacter) {
        .addMapping(generatedLine, generatedCharacter);
    }
    void addMapping(long generatedLine, long generatedCharacter, long sourceIndex, long sourceLine, long sourceCharacter, long nameIndex = ··null!(long)) {
        .addMapping(generatedLine, generatedCharacter, sourceIndex, sourceLine, sourceCharacter, nameIndex);
    }
    void appendSourceMap(long generatedLine, long generatedCharacter, RawSourceMap sourceMap, dstring sourceMapPath, 行和列_ start = ··null!(行和列_), 行和列_ end = ··null!(行和列_)) {
        .appendSourceMap(generatedLine, generatedCharacter, sourceMap, sourceMapPath, start, end);
    }
    RawSourceMap toJSON() {
        return .toJSON();
    }
    dstring 转为文本() {
        RawSourceMap map = this.toJSON();
        JSON值_ 版本值 = JSON值_(3);
        JSON值_ 空值_;
        JSON值_ ret = 创建JSON空对象();
        ret.设置("version"d, 版本值);
        ret.f·设置!(dstring)("file"d, map.file);
        if (map.sourceRoot !is ··null!(dstring)) {
            JSON值_ 源根值 = JSON值_(map.sourceRoot);
            ret.设置("sourceRoot"d, 源根值);
        }
        else {
            ret.设置("sourceRoot"d, JSON值_(""d));
        }
        JSON值_[] 源组 = 创建数组!(JSON值_)();
        循环每个!(dstring, bool)(map.sources, (dstring s, size_t _) {
            JSON值_ sv = JSON值_(s);
            .追加!(JSON值_)(源组, sv);
            return false;
        });
        ret.设置("sources"d, JSON值_(源组));
        if (map.sourcesContent !is ··null!(dstring[])) {
            JSON值_[] 源内容组 = 创建数组!(JSON值_)();
            循环每个!(dstring, bool)(map.sourcesContent, (dstring s, size_t _) {
                JSON值_ sv = JSON值_(s);
                .追加!(JSON值_)(源内容组, sv);
                return false;
            });
            ret.设置("sourcesContent"d, JSON值_(源内容组));
        }
        ret.设置("mappings"d, JSON值_(map.mappings));
        JSON值_[] 名称组 = 创建数组!(JSON值_)();
        if (map.names !is ··null!(dstring[])) {
            循环每个!(dstring, bool)(map.names, (dstring s, size_t _) {
                JSON值_ sv = JSON值_(s);
                .追加!(JSON值_)(名称组, sv);
                return false;
            });
        }
        ret.设置("names"d, JSON值_(名称组));
        return ret.转为文本();
    }
}
class 迭代器_(T) {
    T value;
    bool done;
    this() { }
    this(T _v, bool _done) {
        this.value = _v;
        this.done = _done;
    }
}
class MappingsDecoder {
    dstring mappings;
    long pos;
    dstring error;
    bool done = false;
    long generatedLine = 0;
    long generatedCharacter = 0;
    long sourceIndex = 0;
    long sourceLine = 0;
    long sourceCharacter = 0;
    long nameIndex = 0;
    this() { }
    this(dstring _mappings) {
        this.mappings = _mappings;
        this.pos = 0;
        this.error = ""d;
    }
    Mapping state() {
        return this.captureMapping(true, true);
    }
    迭代器_!(Mapping) next() {
        while(!this.done && this.pos < this.mappings.length) {
            immutable(dchar) ch = this.mappings[this.pos];
            if (ch == 字符_.分号) {
                // new line
                ++this.generatedLine;
                this.generatedCharacter = 0;
                ++this.pos;
                continue;
            }
            if (ch == 字符_.逗号) {
                // Next entry is on same line - no action needed
                ++this.pos;
                continue;
            }
            bool hasSource = false;
            bool hasName = false;
            this.generatedCharacter += this.base64VLQFormatDecode();
            if (this.hasReportedError()) {
                return this.stopIterating();
            }
            if (this.generatedCharacter < 0) {
                return this.setErrorAndStopIterating("Invalid generatedCharacter found"d);
            }
            if (!this.isSourceMappingSegmentEnd()) {
                hasSource = true;
                this.sourceIndex += this.base64VLQFormatDecode();
                if (this.hasReportedError()) {
                    return this.stopIterating();
                }
                if (this.sourceIndex < 0) {
                    return this.setErrorAndStopIterating("Invalid sourceIndex found"d);
                }
                if (this.isSourceMappingSegmentEnd()) {
                    return this.setErrorAndStopIterating("Unsupported Format: No entries after sourceIndex"d);
                }
                this.sourceLine += this.base64VLQFormatDecode();
                if (this.hasReportedError()) {
                    return this.stopIterating();
                }
                if (this.sourceLine < 0) {
                    return this.setErrorAndStopIterating("Invalid sourceLine found"d);
                }
                if (this.isSourceMappingSegmentEnd()) {
                    return this.setErrorAndStopIterating("Unsupported Format: No entries after sourceLine"d);
                }
                this.sourceCharacter += this.base64VLQFormatDecode();
                if (this.hasReportedError()) {
                    return this.stopIterating();
                }
                if (this.sourceCharacter < 0) {
                    return this.setErrorAndStopIterating("Invalid sourceCharacter found"d);
                }
                if (!this.isSourceMappingSegmentEnd()) {
                    hasName = true;
                    this.nameIndex += this.base64VLQFormatDecode();
                    if (this.hasReportedError()) {
                        return this.stopIterating();
                    }
                    if (this.nameIndex < 0) {
                        return this.setErrorAndStopIterating("Invalid nameIndex found"d);
                    }
                    if (!this.isSourceMappingSegmentEnd()) {
                        return this.setErrorAndStopIterating("Unsupported Error Format: Entries after nameIndex"d);
                    }
                }
            }
            return new 迭代器_!(Mapping)(this.captureMapping(hasSource, hasName), this.done);
        }
        return this.stopIterating();
    }
    long base64VLQFormatDecode() {
        bool moreDigits = true;
        long shiftCount = 0;
        long value = 0;
        for (; moreDigits; ++this.pos) {
            if (this.pos >= this.mappings.length) {
                this.setError("Error in decoding base64VLQFormatDecode, past the mapping 文本"d);
                return -1;
            }
            // 6 digit 整数_
            long currentByte = .base64FormatDecode((cast(整数_)(this.mappings[this.pos])));
            if (currentByte == -1) {
                this.setError("Invalid character in VLQ"d);
                return -1;
            }
            // If msb is set, we still have more bits to 继续
            moreDigits = (currentByte & 32) != 0;
            // least significant 5 bits are the next msbs in the final value.
            value = value | ((currentByte & 31) << shiftCount);
            shiftCount += 5;
        }
        // Least significant bit 如果 1 represents negative and rest 属于 the msb is actual absolute value
        if ((value & 1) == 0) {
            // + 整数_
            value = value >> 1;
        }
        else {
            // - 整数_
            value = value >> 1;
            value = -value;
        }
        return value;
    }
    void setError(dstring message) {
        this.error = message;
    }
    迭代器_!(Mapping) stopIterating() {
        this.done = true;
        return new 迭代器_!(Mapping)(返回零值!(Mapping)(), this.done);
    }
    迭代器_!(Mapping) setErrorAndStopIterating(dstring message) {
        this.setError(message);
        return this.stopIterating();
    }
    bool hasReportedError() {
        return this.error !is ··null!(dstring);
    }
    bool isSourceMappingSegmentEnd() {
        return (this.pos == this.mappings.length || this.mappings[this.pos] == 字符_.逗号 || this.mappings[this.pos] == 字符_.分号);
    }
    Mapping captureMapping(bool hasSource, bool hasName) {
        return new Mapping(this.generatedLine, this.generatedCharacter, hasSource ? this.sourceIndex : -1, hasSource ? this.sourceLine : -1, hasSource ? this.sourceCharacter : -1, hasName ? this.nameIndex : -1);
    }
}
class Mapping {
    long generatedLine;
    long generatedCharacter;
    long sourceIndex;
    long sourceLine;
    long sourceCharacter;
    long nameIndex;
    this() { }
    this(long _generatedLine, long _generatedCharacter, long _sourceIndex = ··null!(long), long _sourceLine = ··null!(long), long _sourceCharacter = ··null!(long), long _nameIndex = ··null!(long)) {
        this.generatedLine = _generatedLine;
        this.generatedCharacter = _generatedCharacter;
        this.sourceIndex = _sourceIndex;
        this.sourceLine = _sourceLine;
        this.sourceCharacter = _sourceCharacter;
        this.nameIndex = _nameIndex;
    }
}
struct LineInfo_ {
    long delegate() getLineCount;
    dstring delegate(long) getLineText;
    this(long delegate() _getLineCount, dstring delegate(long) _getLineText) {
        this.getLineCount = cast(long delegate())(_getLineCount);
        this.getLineText = cast(dstring delegate(long))(_getLineText);
    }
}
SourceMapGenerator createSourceMapGenerator(程序主机接口_ host, dstring file, dstring sourceRoot, dstring sourcesDirectoryPath) {
    ._sourcesDirectoryPath = sourcesDirectoryPath;
    ._host = host;
    ._file = file;
    ._sourceRoot = sourceRoot;
    .rawSources = 创建数组!(dstring)(); // [];
    .sources = 创建数组!(dstring)(); //;
    .sourceToSourceIndexMap = new 词典_!(long)();
    .names = 创建数组!(dstring)(); //;
    .mappingCharCodes = 创建数组!(const(dchar))(); //;
    .mappings = ""d;
    // Last recorded and encoded mappings
    .lastGeneratedLine = 0;
    .lastGeneratedCharacter = 0;
    .lastSourceIndex = 0;
    .lastSourceLine = 0;
    .lastSourceCharacter = 0;
    .lastNameIndex = 0;
    .hasLast = false;
    .pendingGeneratedLine = 0;
    .pendingGeneratedCharacter = 0;
    .pendingSourceIndex = 0;
    .pendingSourceLine = 0;
    .pendingSourceCharacter = 0;
    .pendingNameIndex = 0;
    .hasPending = false;
    .hasPendingSource = false;
    .hasPendingName = false;
    return new KlangSourceMapGenerator();
}
RawSourceMap toJSON() {
    .commitPendingMapping();
    .flushMappingBuffer();
    return new RawSourceMap(._file, .sources, .mappings, ._sourceRoot, .sourcesContent, .names);
}
long addSource(dstring fileName) {
    dstring source = 获取相对路径到目录或URL(._sourcesDirectoryPath, fileName, _host.获取当前目录(), (dstring 文件名) { return _host.getCanonicalFileName(文件名); }, 
    /*isAbsolutePathAnUrl*/ true);
    long sourceIndex = 0;
    if (!sourceToSourceIndexMap.具有(source)) {
        sourceIndex = sources.length;
        .追加!(dstring)(.sources, source);
        .追加!(dstring)(.rawSources, fileName);
        sourceToSourceIndexMap.p·设置(source, sourceIndex);
    }
    return sourceToSourceIndexMap.获取(source);
}
/* eslint-disable boolean-trivia, no-null/no-null */
void setSourceContent(long sourceIndex, dstring content) {
    if (content != "\0"d) {
        if (.sourcesContent is ··null!(dstring[])) {
            .sourcesContent = 创建数组!(dstring)();
        }
        while(sourcesContent.length < sourceIndex) {
            .追加!(dstring)(.sourcesContent, "\0"d);
        }
        if (sourcesContent.length == sourceIndex) {
            sourcesContent.length = sourceIndex + 1;
        }
        sourcesContent[sourceIndex] = content;
    }
}
/* eslint-enable boolean-trivia, no-null/no-null */
long addName(dstring name) {
    if ((.nameToNameIndexMap is null) || (.nameToNameIndexMap.原型 is ··null!(long[dstring]))) {
        .nameToNameIndexMap = new 词典_!(long)();
    }
    long nameIndex = 0;
    if (!nameToNameIndexMap.具有(name)) {
        nameIndex = names.length;
        .追加!(dstring)(.names, name);
        nameToNameIndexMap.p·设置(name, nameIndex);
    }
    return nameIndex;
}
bool isNewGeneratedPosition(long generatedLine, long generatedCharacter) {
    return !.hasPending || .pendingGeneratedLine != generatedLine || .pendingGeneratedCharacter != generatedCharacter;
}
bool isBacktrackingSourcePosition(long sourceIndex, long sourceLine, long sourceCharacter) {
    return sourceIndex != -1 && sourceLine != -1 && sourceCharacter != -1 && .pendingSourceIndex == sourceIndex && (.pendingSourceLine > sourceLine || .pendingSourceLine == sourceLine && .pendingSourceCharacter > sourceCharacter);
}
void addMapping(long generatedLine, long generatedCharacter, long sourceIndex = -1, long sourceLine = -1, long sourceCharacter = -1, long nameIndex = -1) {
    // If this location wasn't recorded or the location in source is going backwards, record the mapping
    if (.isNewGeneratedPosition(generatedLine, generatedCharacter) || .isBacktrackingSourcePosition(sourceIndex, sourceLine, sourceCharacter)) {
        .commitPendingMapping();
        .pendingGeneratedLine = generatedLine;
        .pendingGeneratedCharacter = generatedCharacter;
        .hasPendingSource = false;
        .hasPendingName = false;
        .hasPending = true;
    }
    if (sourceIndex != -1 && sourceLine != -1 && sourceCharacter != -1) {
        .pendingSourceIndex = sourceIndex;
        .pendingSourceLine = sourceLine;
        .pendingSourceCharacter = sourceCharacter;
        .hasPendingSource = true;
        if (nameIndex != -1) {
            .pendingNameIndex = nameIndex;
            .hasPendingName = true;
        }
    }
}
void appendSourceMap(long generatedLine, long generatedCharacter, RawSourceMap map, dstring sourceMapPath, 行和列_ start = ··null!(行和列_), 行和列_ end = ··null!(行和列_)) {
    // First, decode the old component sourcemap
    long[] sourceIndexToNewSourceIndexMap = 创建数组!(long)();
    long[] nameIndexToNewNameIndexMap;
    MappingsDecoder mappingIterator = new MappingsDecoder(map.mappings);
    {
        for (迭代器_!(Mapping) iterResult = mappingIterator.next(); !iterResult.done; iterResult = mappingIterator.next()) {
            Mapping raw = iterResult.value;
            if ((end !is ··null!(行和列_)) && (raw.generatedLine > end.行 || (raw.generatedLine == end.行 && raw.generatedCharacter > end.列))) {
                break;
            }
            if ((start !is ··null!(行和列_)) && (raw.generatedLine < start.行 || (start.行 == raw.generatedLine && raw.generatedCharacter < start.列))) {
                continue;
            }
            // Then reencode all the updated mappings into the overall map
            long newSourceIndex = -1;
            long newSourceLine = -1;
            long newSourceCharacter = -1;
            long newNameIndex = -1;
            if (raw.sourceIndex != -1) {
                newSourceIndex = sourceIndexToNewSourceIndexMap[raw.sourceIndex];
                if (newSourceIndex == -1) {
                    // Apply offsets to each position and fixup source entries
                    dstring rawPath = map.sources[raw.sourceIndex];
                    dstring relativePath = map.sourceRoot ? 组合路径(map.sourceRoot, [rawPath]) : rawPath;
                    dstring combinedPath = 组合路径(获取目录路径(sourceMapPath), [relativePath]);
                    newSourceIndex = .addSource(combinedPath);
                    sourceIndexToNewSourceIndexMap[raw.sourceIndex] = newSourceIndex;
                    if ((map.sourcesContent !is ··null!(dstring[])) && (map.sourcesContent[raw.sourceIndex] !is ··null!(dstring))) {
                        .setSourceContent(newSourceIndex, map.sourcesContent[raw.sourceIndex]);
                    }
                }
                newSourceLine = raw.sourceLine;
                newSourceCharacter = raw.sourceCharacter;
                if ((map.names !is ··null!(dstring[])) && raw.nameIndex != -1) {
                    long[] ···temp·0·_1 = nameIndexToNewNameIndexMap;
                    if (···temp·0·_1 is ··null!(long[])) {
                        nameIndexToNewNameIndexMap = 创建数组!(long)();
                    }
                    newNameIndex = nameIndexToNewNameIndexMap[raw.nameIndex];
                    if (newNameIndex == -1) {
                        nameIndexToNewNameIndexMap[raw.nameIndex] = newNameIndex = .addName(map.names[raw.nameIndex]);
                    }
                }
            }
            long rawGeneratedLine = raw.generatedLine - ((start !is ··null!(行和列_)) ? start.行 : 0);
            long newGeneratedLine = rawGeneratedLine + generatedLine;
            long rawGeneratedCharacter = (start !is ··null!(行和列_)) && start.行 == raw.generatedLine ? raw.generatedCharacter - start.列 : raw.generatedCharacter;
            long newGeneratedCharacter = rawGeneratedLine == 0 ? rawGeneratedCharacter + generatedCharacter : rawGeneratedCharacter;
            .addMapping(newGeneratedLine, newGeneratedCharacter, newSourceIndex, newSourceLine, newSourceCharacter, newNameIndex);
        }
    }
}
bool shouldCommitMapping() {
    return !.hasLast || .lastGeneratedLine != .pendingGeneratedLine || .lastGeneratedCharacter != .pendingGeneratedCharacter || .lastSourceIndex != .pendingSourceIndex || .lastSourceLine != .pendingSourceLine || .lastSourceCharacter != .pendingSourceCharacter || .lastNameIndex != .pendingNameIndex;
}
void appendMappingCharCode(long charCode) {
    .追加!(const(dchar))(.mappingCharCodes, (cast(dchar)(charCode)));
    // String.fromCharCode accepts its arguments on the stack, so we have to chunk the input,
    // otherwise we can get stack overflows 循环 large source maps
    if (mappingCharCodes.length >= 1024) {
        .flushMappingBuffer();
    }
}
void commitPendingMapping() {
    if (!.hasPending || !.shouldCommitMapping()) {
        return;
    }
    // Line/Comma delimiters
    if (.lastGeneratedLine < .pendingGeneratedLine) {
        // Emit 行 delimiters
        .appendMappingCharCode(字符_.分号);
        ++lastGeneratedLine;
        while(.lastGeneratedLine < .pendingGeneratedLine) {
            .appendMappingCharCode(字符_.分号);
            ++lastGeneratedLine;
        }
        // Only need to set this once
        .lastGeneratedCharacter = 0;
    }
    else {
        // Emit comma to separate the entry
        if (.hasLast) {
            .appendMappingCharCode(字符_.逗号);
        }
    }
    // 1. Relative generated 列
    .appendBase64VLQ(.pendingGeneratedCharacter - .lastGeneratedCharacter);
    .lastGeneratedCharacter = .pendingGeneratedCharacter;
    if (.hasPendingSource) {
        // 2. Relative sourceIndex
        .appendBase64VLQ(.pendingSourceIndex - .lastSourceIndex);
        .lastSourceIndex = .pendingSourceIndex;
        // 3. Relative source 行
        .appendBase64VLQ(.pendingSourceLine - .lastSourceLine);
        .lastSourceLine = .pendingSourceLine;
        // 4. Relative source 列
        .appendBase64VLQ(.pendingSourceCharacter - .lastSourceCharacter);
        .lastSourceCharacter = .pendingSourceCharacter;
        if (.hasPendingName) {
            // 5. Relative nameIndex
            .appendBase64VLQ(.pendingNameIndex - .lastNameIndex);
            .lastNameIndex = .pendingNameIndex;
        }
    }
    .hasLast = true;
}
void flushMappingBuffer() {
    if (mappingCharCodes.length > 0) {
        .mappings ~= ·to!(dstring)(.mappingCharCodes);
        mappingCharCodes.length = 0;
    }
}
void appendBase64VLQ(long inValue) {
    // Add a new least significant bit that has the sign 属于 the value.
    // 如果 negative 整数_ the least significant bit that gets added to the 整数_ has value 1
    // 否则 least significant bit value that gets added is 0
    // eg. -1 changes to binary : 01 [1] => 3
    //     +1 changes to binary : 01 [0] => 2
    if (inValue < 0) {
        inValue = ((-inValue) << 1) + 1;
    }
    else {
        inValue = inValue << 1;
    }
    long currentDigit = inValue & 31; // 11111
    inValue = inValue >> 5;
    if (inValue > 0) {
        // There are still more digits to decode, set the msb (6th bit)
        currentDigit = currentDigit | 32;
    }
    .appendMappingCharCode(.base64FormatEncode(currentDigit));
    // Encode 5 bits at a time starting from least significant bits
    while(inValue > 0) {
        currentDigit = inValue & 31; // 11111
        inValue = inValue >> 5;
        if (inValue > 0) {
            // There are still more digits to decode, set the msb (6th bit)
            currentDigit = currentDigit | 32;
        }
        .appendMappingCharCode(.base64FormatEncode(currentDigit));
    }
}
LineInfo_ getLineInfo(dstring text, long[] lineStarts) {
    return .LineInfo_(() { return lineStarts.length; }, (整数_ line) { return text[lineStarts[line] .. lineStarts[line + 1]]; });
}
/**
 * Tries to find the sourceMappingURL comment at the end 属于 a file.
 */
dstring tryGetSourceMappingURL(LineInfo_ lineInfo) {
    {
        for (long index = lineInfo.getLineCount() - 1; index >= 0; --index) {
            dstring line = lineInfo.getLineText(index);
            匹配结果_!(dstring) comment = sourceMapCommentRegExp.p·匹配(line);
            if (!comment.empty()) {
                return trimEndImpl(comment.captures()[1]);
            }
            // If we see a non-whitespace/map comment-like line, 跳出, to avoid scanning up the entire file
            else 
            // If we see a non-whitespace/map comment-like line, 跳出, to avoid scanning up the entire file
            if (whitespaceOrMapCommentRegExp.p·匹配(line).empty()) {
                break;
            }
        }
    }
    return ··null!(dstring);
}
bool sameMapping(Mapping left, Mapping right) {
    return left == right || left.generatedLine == right.generatedLine && left.generatedCharacter == right.generatedCharacter && left.sourceIndex == right.sourceIndex && left.sourceLine == right.sourceLine && left.sourceCharacter == right.sourceCharacter && left.nameIndex == right.nameIndex;
}
bool isSourceMapping(Mapping mapping) {
    return mapping.sourceIndex != -1 && mapping.sourceLine != -1 && mapping.sourceCharacter != -1;
}
long base64FormatEncode(long value) {
    return value >= 0 && value < 26 ? 字符_.A + value : value >= 26 && value < 52 ? 字符_.a + value - 26 : value >= 52 && value < 62 ? 字符_.数_0 + value - 52 : value == 62 ? 字符_.加号 : value == 63 ? 字符_.斜杠 : -1;
}
long base64FormatDecode(long ch) {
    return ch >= 字符_.A && ch <= 字符_.Z ? ch - 字符_.A : ch >= 字符_.a && ch <= 字符_.z ? ch - 字符_.a + 26 : ch >= 字符_.数_0 && ch <= 字符_.数_9 ? ch - 字符_.数_0 + 52 : ch == 字符_.加号 ? 62 : ch == 字符_.斜杠 ? 63 : -1;
}
